package com.dhcc.bpm.alarm.utils;

import com.alibaba.fastjson.JSONObject;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpProgressMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

public class SftpUtils {

    public static final Boolean SFTP_TYPE_DOWNLOAD = true;
    public static final Boolean SFTP_TYPE_UPLOAD = false;
    private static int CHANNEL_TIMEOUT = 1000*60*10;

    private static Logger LOGGER = LoggerFactory.getLogger(SftpUtils.class);


    public static JSONObject sftp(JSONObject sessionJson, String srcPath, String destPath, String srcName, String destName, Boolean flag, Boolean sftpType) {
        if (sftpType)
            return sftpDownload(sessionJson, srcPath, destPath, srcName, destName, flag);
        return sftpUpload(sessionJson, srcPath, destPath, srcName, destName, flag);
    }





    public static JSONObject sftpUpload(JSONObject sessionJson, String srcPath, String destPath, String srcName, String destName, Boolean flag, SftpProgressMonitor monitor) {

        ChannelSftp c = null;
        JSONObject json = new JSONObject();
        String caseName = sessionJson.getString("caseName");
        json.put("caseName", caseName);
        Session session = (Session) sessionJson.get("session");
        if (session == null) {
            json.put("message", sessionJson.getString("message"));
            json.put("code", false);
            return json;
        }
        if (!session.isConnected()) {
            json.put("message", "session已关闭");
            json.put("code", false);
            return json;
        }
        InputStream fis = null;
        OutputStream os = null;
        try {
            Channel channel = session.openChannel("sftp");
            channel.connect(CHANNEL_TIMEOUT);
            c = (ChannelSftp) channel;
            c.cd(destPath);

            String pwd = c.pwd();
            LOGGER.info("进入文件夹:" + pwd);
            String src = BaseUtils.fullPath(srcPath, srcName);
            String dst = BaseUtils.fullPath(pwd, destName);
            if(monitor==null){
                monitor = new UploadMonitor(caseName,new File(src).length());
            }

            //是否限制上传速度
            boolean speedLimit = true;
            if (speedLimit) {
                os = c.put(dst, monitor, ChannelSftp.OVERWRITE);
                byte[] buff = new byte[1024 * 256]; // 设定每次传输的数据块大小为256KB
                int read;
                if (os != null) {
                    fis = new FileInputStream(src);
                    do {
                        read = fis.read(buff, 0, buff.length);
                        if (read > 0) {
                            os.write(buff, 0, read);
                        }
                        os.flush();
                    } while (read >= 0);
                }
            } else {

                c.put(src, dst, monitor, ChannelSftp.OVERWRITE);
            }
            json.put("message", "文件上传成功!");
            json.put("code", true);
        } catch (Exception e) {
            LOGGER.error("文件上传发生错误:{}", e);
            json.put("message", e.getCause().getLocalizedMessage());
            json.put("code", false);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (c != null) {
                c.disconnect();
            }
            if (flag){
                session.disconnect();
            }


        }
        return json;

    }


    public static JSONObject sftpUpload(JSONObject sessionJson, String srcPath, String destPath, String srcName, String destName, Boolean flag) {
        return sftpUpload(sessionJson,srcPath,destPath,srcName,destName,flag,null);
    }


    public static JSONObject sftpUploadStream(JSONObject sessionJson, InputStream inputStream, String destPath, String destName, Boolean flag,SftpProgressMonitor monitor) {
        ChannelSftp c = null;
        JSONObject json = new JSONObject();
        String caseName = sessionJson.getString("caseName");
        json.put("caseName", caseName);
        Session session = (Session) sessionJson.get("session");
        if (session == null) {
            json.put("message", sessionJson.getString("message"));
            json.put("code", false);
            return json;
        }
        if (!session.isConnected()) {
            json.put("message", "session已关闭");
            json.put("code", false);
            return json;
        }
        InputStream fis = null;
        OutputStream os = null;
        try {
            Channel channel = session.openChannel("sftp");
            channel.connect(CHANNEL_TIMEOUT);
            c = (ChannelSftp) channel;
            c.cd(destPath);

            String pwd = c.pwd();
            LOGGER.info("进入文件夹:" + pwd);

            String dst = BaseUtils.fullPath(pwd, destName);
            if(monitor==null){
                monitor = new UploadMonitor(caseName,inputStream.available());
            }
            //是否限制上传速度
            boolean speedLimit = true;
            if (speedLimit) {
                os = c.put(dst, monitor, ChannelSftp.OVERWRITE);
                byte[] buff = new byte[1024 * 256]; // 设定每次传输的数据块大小为256KB
                int read;
                if (os != null) {
                    fis = inputStream;
                    do {
                        read = fis.read(buff, 0, buff.length);
                        if (read > 0) {
                            os.write(buff, 0, read);
                        }
                        os.flush();
                    } while (read >= 0);
                }
            } else {
                c.put(dst, monitor, ChannelSftp.OVERWRITE);
            }
            json.put("message", "文件上传成功!");
            json.put("code", true);
        } catch (Exception e) {
            LOGGER.error("文件上传发生错误:{}", e);
            json.put("message", e.getCause().getLocalizedMessage());
            json.put("code", false);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (c != null) {
                c.disconnect();
            }
            if (flag)
                session.disconnect();

        }
        return json;

    }

    public static JSONObject sftpUploadStream(JSONObject sessionJson, InputStream inputStream, String destPath, String destName, Boolean flag) {
        return sftpUploadStream(sessionJson,inputStream,destPath,destName,flag,null);
    }

    @SuppressWarnings({ "deprecation", "finally" })
    public static JSONObject sftpDownload(JSONObject sessionJson, String srcPath, String destPath, String srcName, String destName, Boolean flag,SftpProgressMonitor monitor) {
        ChannelSftp c = null;
        JSONObject json = new JSONObject();
        String caseName = sessionJson.getString("caseName");
        json.put("caseName", caseName);
        Session session = (Session) sessionJson.get("session");
        if (session == null) {
            json.put("message", sessionJson.getString("message"));
            json.put("code", false);
            return json;
        }
        if (!session.isConnected()) {
            json.put("message", "session已关闭");
            json.put("code", false);
            return json;
        }
        InputStream is = null;
        FileOutputStream fos = null;

        try {
            Channel channel = session.openChannel("sftp");
            channel.connect(CHANNEL_TIMEOUT);
            c = (ChannelSftp) channel;
            c.cd(destPath);
            String pwd = c.pwd();
            LOGGER.info("进入文件夹:" + pwd);
            String src = BaseUtils.fullPath(srcPath, srcName);
            String dst = BaseUtils.fullPath(pwd, destName);
            if(monitor==null){
                monitor = new DownloadMonitor(caseName);
            }
            boolean speedLimit = false;

            if (speedLimit) {

                is = c.get(dst, monitor, ChannelSftp.OVERWRITE);
                byte[] buff = new byte[1024 * 256];
                int read;

                if (is != null) {
                    fos = new FileOutputStream(src);
                    do {
                        read = is.read(buff, 0, buff.length);
                        if (read > 0) {
                            fos.write(buff, 0, read);
                        }
                        fos.flush();

                    } while (read >= 0);
                }
            } else {
                c.get(dst, src, monitor, ChannelSftp.OVERWRITE);
            }

            json.put("message", "文件下载成功!");
            json.put("code", true);
        } catch (Exception e) {
            LOGGER.error("文件下载发生错误:{}", e);
            json.put("message", e.getCause().getLocalizedMessage());
            json.put("code", false);
        } finally {

            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    LOGGER.error("文件流关闭发生错误:{}", e);
                }
            }
            if (c != null) {
                c.disconnect();
            }
            if (flag)
                session.disconnect();
            return json;

        }
    }

    public static JSONObject sftpDownload(JSONObject sessionJson, String srcPath, String destPath, String srcName, String destName, Boolean flag) {
        return sftpDownload(sessionJson,srcPath,destPath,srcName,destName,flag,null);
    }
}

